package com.wbl.train.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wbl.train.business.service.TrainStationService;
import com.wbl.train.common.business.dto.DailyTrainStationDto;
import com.wbl.train.common.business.entity.*;
import com.wbl.train.business.mapper.DailyTrainStationMapper;
import com.wbl.train.business.service.DailyTrainStationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wbl.train.common.exception.ApplicationException;
import com.wbl.train.common.page.PageVo;
import com.wbl.train.common.result.ResultCode;
import com.wbl.train.common.utils.SnowUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 每日车站 服务实现类
 * @author 王博纶
 * @since 2024-02-11
 */
@AllArgsConstructor
@Slf4j
@Service
public class DailyTrainStationServiceImpl extends ServiceImpl<DailyTrainStationMapper, DailyTrainStationEntity> implements DailyTrainStationService {

    private final TrainStationService trainStationService;

    @Override
    public PageVo<DailyTrainStationEntity> queryTrainStation(DailyTrainStationDto dailyTrainStationDto) {
        // 获取分页所需要的参数
        int page = dailyTrainStationDto.getPage();
        int limit = dailyTrainStationDto.getLimit();

        LambdaQueryWrapper<DailyTrainStationEntity> dailyTrainStationWrapper = new LambdaQueryWrapper<DailyTrainStationEntity>()
                .eq(ObjectUtil.isNotEmpty(dailyTrainStationDto.getTrainCode()),DailyTrainStationEntity::getTrainCode,dailyTrainStationDto.getTrainCode())
                .eq(ObjectUtil.isNotNull(dailyTrainStationDto.getDate()),DailyTrainStationEntity::getDate,dailyTrainStationDto.getDate())
                .orderByDesc(DailyTrainStationEntity::getDate)
                .orderByAsc(DailyTrainStationEntity::getTrainCode)
                .orderByAsc(DailyTrainStationEntity::getStationIndex);

        //创建分页对象
        IPage<DailyTrainStationEntity> dailyTrainStationPage = new Page<>(page,limit);
        //调用分页方法
        IPage<DailyTrainStationEntity> dailyTrainStationPageData = page(dailyTrainStationPage,dailyTrainStationWrapper);
        // 获取查询出来的数据集合
        List<DailyTrainStationEntity> records = dailyTrainStationPageData.getRecords();
        // 将数据塞到PageVo类中并返回出去
        return new PageVo<DailyTrainStationEntity>()
                .setDataList(records)
                .setPageSize(limit).setCurrentPage(page)
                .setTotal((int) dailyTrainStationPageData.getTotal())
                .setPages((int) dailyTrainStationPageData.getPages());
    }

    @Override
    public boolean insertAndUpdateTrain(DailyTrainStationEntity dailyTrainStation) {
        // 获取当前的时间 --- 用于创建和修改的时候的时间填充
        DateTime now = DateTime.now();
        // 设置火车车站的修改时间
        dailyTrainStation.setUpdateTime(now);
        // 判断Id是否为空
        if(ObjectUtil.isNotNull(dailyTrainStation.getId())){
            // 根据id查询火车车站信息
            DailyTrainStationEntity dailyTrainStationEntity = this.getById(dailyTrainStation.getId());
            // 当前id对应的无火车车站信息
            if(ObjectUtil.isNull(dailyTrainStationEntity)){
                throw new ApplicationException(ResultCode.DATA_NOT_EXIST,"当前火车车站不存在");
            }
            // 更新火车车次信息
            return this.updateById(dailyTrainStation);
        }
        // 保存之前的唯一键校验
        DailyTrainStationEntity dailyTrainStationEntity = getTrainStationByUniqueKey(dailyTrainStation.getDate(),dailyTrainStation.getTrainCode(),dailyTrainStation.getStationIndex());
        // 查询出的trainEntity不为空，不允许新增
        if(ObjectUtil.isNotEmpty(dailyTrainStationEntity)){
            throw new ApplicationException(ResultCode.DATA_EXIST,"当前火车车次已存在");
        }
        // 给新增的火车车站设置Id，创建时间和修改时间
        dailyTrainStation.setId(SnowUtil.getSnowflakeNextId())
                .setCreateTime(now);
        // 新增火车车站
        return this.save(dailyTrainStation);
    }

    /**
     * 根据唯一键查询 trainStation 火车车站信息
     * @param date 当日日期
     * @param trainCode 火车车次编号
     * @param stationIndex 车站序号
     * @return trainStation 火车车站信息
     */
    private DailyTrainStationEntity getTrainStationByUniqueKey(LocalDate date, String trainCode, Integer stationIndex) {
        // 通过trainCode和stationIndex进行火车车站信息联合主键，进行去重查询
        LambdaQueryWrapper<DailyTrainStationEntity> wrapper = new LambdaQueryWrapper<DailyTrainStationEntity>()
                .eq(DailyTrainStationEntity::getDate,date)
                .eq(DailyTrainStationEntity::getTrainCode, trainCode)
                .eq(DailyTrainStationEntity::getStationIndex, stationIndex);
        return this.getOne(wrapper);
    }

    @Transactional
    public void genDailyStation(LocalDate date, String trainCode,Date now) {
        log.info("生成日期【{}】车次【{}】的车站信息开始",date,trainCode);
        ArrayList<DailyTrainStationEntity> dailyTrainStationList = new ArrayList<>();
        // 删除某日某车次的车站信息
        LambdaUpdateWrapper<DailyTrainStationEntity> deleteWrapper = new LambdaUpdateWrapper<DailyTrainStationEntity>()
                .eq(DailyTrainStationEntity::getTrainCode, trainCode)
                .eq(DailyTrainStationEntity::getDate, date);
        this.remove(deleteWrapper);

        // 查出某车次的所有的车站信息
        List<TrainStationEntity> trainStations = trainStationService.selectByTrainCode(trainCode);
        if(CollUtil.isEmpty(trainStations)){
            log.error("没有车站基础数据，生成改车次车站信息结束");
            throw new ApplicationException(ResultCode.DATA_NOT_EXIST,"没有车站基础数据，生成改车次车站信息结束");
        }

        for (TrainStationEntity trainStation : trainStations) {
            // 生成每日车次
            dailyTrainStationList.add(BeanUtil.copyProperties(trainStation, DailyTrainStationEntity.class)
                    .setId(SnowUtil.getSnowflakeNextId())
                    .setDate(date)
                    .setCreateTime(now)
                    .setUpdateTime(now));
        }
        this.saveBatch(dailyTrainStationList);
        log.info("生成日期【{}】车次【{}】的车站信息结束",date,trainCode);
    }
}
